from django.shortcuts import render
from django.http import JsonResponse
from django.shortcuts import HttpResponse
from django.views import View
from django.urls import reverse
from django.forms import model_to_dict
from web.forms.file import FileModelForm
from django.views.decorators.csrf import csrf_exempt
from web.forms.file import FolderModelForm
from web import models
from utils.tencent.cos import delete_file
from utils.tencent.cos import delete_file_list
from utils.tencent.cos import credential
import json
import requests

class FileView(View):

    def get(self,request,project_id):
        #文件页面展示

        #是否时根目录
        parent_object = None
        parent=None
        folder_id = request.GET.get('folder', '')
        #如果不是 则 查找父目录对象
        if folder_id.isdecimal():
            parent_object = models.FileRepository.objects.filter(id=int(folder_id), file_type=2,project=request.tracer.project).first()
        #面包屑导航对象列表
        breadcrumb_list=[]
        #生成面包屑导航方法
        if parent_object:
            parent=models.FileRepository.objects.filter(id=int(folder_id)).first()
        # parent=parent_object
        while parent:
            breadcrumb_list.insert(0,model_to_dict(parent,['id','name']))
            parent=parent.parent
        #当前文件&文件夹列表
        queryset=models.FileRepository.objects.filter(project=request.tracer.project)
        #如果不是根目录
        if parent_object:
            file_object_list=queryset.filter(parent=parent_object).order_by('-file_type')
        else:
            file_object_list=queryset.filter(parent__isnull=True).order_by('-file_type')
        #为了创建文件夹 模态对话框需要的
        form=FolderModelForm(request,parent_object)
        #返回给前端的字典
        context={
            'form':form,
            'file_object_list':file_object_list,
            'breadcrumb_list':breadcrumb_list,
            'folder_object':parent_object,
        }
        return render(request,'web/file.html',context)

    def post(self,request,project_id):
        #创建文件夹 & 修改文件夹

        parent_object=None
        folder_id=request.GET.get('folder','')
        if folder_id.isdecimal():
            parent_object=models.FileRepository.objects.filter(id=int(folder_id),file_type=2,project=request.tracer.project).first()
        fid = request.POST.get('fid', '')
        if fid.isdecimal():
            edit_object = models.FileRepository.objects.filter(id=int(fid), project=request.tracer.project).first()
        if edit_object:
            form=FolderModelForm(request,parent_object,data=request.POST,instance=edit_object)
        else:
            form = FolderModelForm(request,parent_object,data=request.POST)
        if form.is_valid():
            form.instance.project=request.tracer.project
            form.instance.file_type=2
            form.instance.update_user=request.tracer.user
            form.instance.parent=parent_object
            form.save()
            return JsonResponse({'status':True})
        else:
            return JsonResponse({'status':False,'error':form.errors})

class FileDeleteView(View):
    '''
    删除文件或文件夹操作
    '''
    def get(self,request,project_id):
        fid=request.GET.get('fid','')
        if fid.isdecimal():
            delete_object=models.FileRepository.objects.filter(project=request.tracer.project,id=int(fid)).first()
        else:
            return JsonResponse({'status':False,'error':'无效的id'})
        #如果删除的是文件
        if delete_object.file_type==1:
            #把用户的项目的使用空间释放
            request.tracer.project.use_space-=delete_object.file_type
            request.tracer.project.save()
            # cos中删除
            delete_file(request.tracer.project.bucket,request.tracer.project.region,delete_object.key)
            #在数据库中删除
            delete_object.delete()
            return JsonResponse({'status':True})
        #删除的是文件夹
        else:
            #文件大小总集合
            total_size=0
            #需要删除的文件的key列表
            key_list=[]
            #文件夹列表
            folder_list=[delete_object,]
            #循环文件夹列表
            for folder in folder_list:
                #在文件夹下 如果是文件  进行 大小汇总  如果是文件夹  添加到 文件夹列表中
                child_list=models.FileRepository.objects.filter(project=request.tracer.project,parent=folder).order_by('-file_type')
                for child in child_list:
                    if child.file_type==2:
                        folder_list.append(child)
                    else:
                        #文件大小汇总
                        total_size+=child.file_size
                        #删除文件列表
                        key_list.append({'key':child.key})
            #进行cos删除
            if key_list:
                delete_file_list(request.tracer.project.bucket,request.tracer.project.region,key_list)
            #归还项目表中使用空间
            if total_size:
                request.tracer.project.use_space-=total_size
                request.tracer.project.save()
            #删除数据库中的数据
            delete_object.delete()
            return JsonResponse({'status':True})

class CosCredentialView(View):
    '''
    获取上传文件的临时凭证
    '''

    @csrf_exempt
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self,request,project_id):
        per_file_limit = request.tracer.price_policy.per_file_size * 1024 * 1024
        total_file_limit = request.tracer.price_policy.project_space * 1024 * 1024 * 1024
        total_size = 0
        file_list = json.loads(request.body.decode('utf8'))
        for item in file_list:
            if item['size']>per_file_limit:
                msg='单文件超出限制（最大{}M），文件：{}，请升级套餐。'.format(request.tracer.price_policy.per_file_size,item['name'])
                return JsonResponse({'status':False,'error':msg})
            total_size+=item['size']
        if request.tracer.project.use_space + total_size > total_file_limit:
            return JsonResponse({'status':False,'error':'容量超过限制，请升级套餐'})

        data_dict = credential(request.tracer.project.bucket, request.tracer.project.region)
        return JsonResponse({'status':True,'data':data_dict})

class FilePostView(View):
    '''
    文件上传成功后  把文件元数据写入 database
    '''

    @csrf_exempt
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self,request,project_id):
        form=FileModelForm(request,data=request.POST)
        if form.is_valid():
            data_dict=form.cleaned_data
            data_dict.pop('etag')
            form.cleaned_data.update({'project':request.tracer.project,'file_type':1,'update_user':request.tracer.user})
            instance=models.FileRepository.objects.create(**data_dict)
            # instance=form.save()
            #更新项目使用空间
            request.tracer.project.use_space += data_dict['file_size']
            request.tracer.project.save()
            result = {
                'id': instance.id,
                'name': instance.name,
                'file_size': instance.file_size,
                'username': instance.update_user.username,
                'datetime': instance.update_datetime.strftime("%Y年%m月%d日 %H:%M"),
                'download_url': reverse('web:manage:file_download', kwargs={"project_id": project_id, 'file_id': instance.id}),
                'file_type': instance.get_file_type_display()
            }
            return JsonResponse({'status':True,'data':result})
        else:
            return JsonResponse({'status':False,'error':form.errors})


class FileDownLoadView(View):
    '''
    下载文件
    '''
    def get(self,request,project_id,file_id):
        file_object=models.FileRepository.objects.filter(id=file_id,project_id=project_id).first()
        res=requests.get(file_object.file_path)
        #文件分块处理  适用于大文件
        data=res.iter_content()
        response=HttpResponse(data,content_type='application/octet-stream')
        # esponse = HttpResponse(data, content_type="application/octet-stream")
        from django.utils.encoding import escape_uri_path
        response['Content-Disposition']="attachment; filename={}".format(escape_uri_path(file_object.name))
        return response